#include "catalog.h"
#include "query.h"
#include "index.h"

/*
 * Inserts a record into the specified relation.
 *
 * Returns:
 * 	OK on success
 * 	an error code otherwise
 */

Status Updates::Insert(const string & relation, 
                             const int attrCnt, 
		             const attrInfo attrList[])
{
	int relnAttrCnt;
	AttrDesc *attrDesc;
	//get the info about this relation
	Status rel_info = attrCat->getRelInfo(relation, relnAttrCnt, attrDesc);
	if(rel_info != OK)
		return rel_info;

	if(relnAttrCnt != attrCnt)
		return INCORRECT_COL_NUM_INSERT;

	//loop through to count the number of bytes needed and re-arrange the data
	int mem_size = 0;
	attrInfo cpy_attrList[attrCnt];
	for(int i = 0; i < relnAttrCnt; i++){
		mem_size += attrDesc[i].attrLen;	
		for(int j = 0; j < attrCnt; j++)
		{
			if(attrList[j].attrName == NULL || attrList[j].relName == NULL ||
				attrList[j].attrValue == NULL)
			{
				return NO_ATTR_VAL;
			}
			if(strcmp(attrDesc[i].attrName, attrList[j].attrName) == 0)
			{
				cpy_attrList[i] = attrList[j];
				break;
			}
			//if this is the last time through the loop and we haven't 
			//found the right attr name return 
			else if(j == (attrCnt - 1))
			{
				return ATTRNOTFOUND;
			}
		}
	}

	Record record;
	record.data = malloc(mem_size);	
	record.length = mem_size;
	int lOffset = 0;
	//loop through the descriptions and insert records
	for(int i = 0; i < attrCnt; i++)
	{
		if(lOffset + attrDesc[i].attrLen > record.length)
			return RECORD_OVERFLOW;

		memcpy((char*)record.data + lOffset, cpy_attrList[i].attrValue, attrDesc[i].attrLen);
		lOffset += attrDesc[i].attrLen;
	} 
	RID rid;
	Status relation_file_status;
	HeapFileScan RelationFile(relation, relation_file_status);

	if(relation_file_status != OK)
		return relation_file_status;

	Status insert_status = RelationFile.insertRecord(record, rid);	
	if(insert_status != OK)
		return insert_status;

	for(int i = 0; i < attrCnt; i++)
	{
		if(attrDesc[i].indexed == true)
		{
			//insert index entry
			Status index_status;
			Index idx(relation, attrDesc[i].attrOffset, attrDesc[i].attrLen,
				(Datatype)attrDesc[i].attrType, false, index_status); 
			if(index_status != OK)
				return index_status;
			Status index_insert = idx.insertEntry(cpy_attrList[i].attrValue, rid);		
			if(index_insert != OK)
				return index_insert;
		}
	}	
	//memory cleanup.  May cause issue in future because relation takes record in
	//by reference
	free(record.data);
	return OK;
}
